Skip to content

Add 0082 Langfuse failed-Generation rendering#232

Merged
chris-colinsky merged 2 commits into
mainfrom
feature/0082-langfuse-failed-generation
Jul 23, 2026
Merged

Add 0082 Langfuse failed-Generation rendering#232
chris-colinsky merged 2 commits into
mainfrom
feature/0082-langfuse-failed-generation

Conversation

@chris-colinsky

Copy link
Copy Markdown
Member

PR C of the 0082 split (structured-output failure diagnostics, spec v0.77.0), completing the proposal. PR A (#229) landed the event + error surface; PR B (#230) the OTel error-span rendering + the token metric; this closes it with the Langfuse side. conformance.toml now marks 0082 implemented.

What

For a structured_output_invalid failure, the bundled Langfuse observer renders the response-side surface on the ERROR Generation like a completion:

  • output (payload-gated) + usage on the Generation;
  • finish_reason / response_id / response_model in metadata (the completion-only isinstance(LlmCompletionEvent) guard in _typed_event_metadata widened to include the category);
  • alongside the existing level = "ERROR" + statusMessage = the category.

Every other failure category is unchanged. Fixture 123 is driven in the dedicated Langfuse harness (_LANGFUSE_FIXTURES), which I taught to thread calls_llm.response_schema and to catch a raising expected_error. Two focused unit tests (rendered / redacted under payload-off).

Whole-proposal adversarial review (folded in)

After all three PRs were done, I ran one adversarial pass over the entire 0082 implementation (cross-observer parity, the retry path, error_message consistency). Findings folded in:

  • Cross-observer consistency: the failure event builders now project empty output_content to None (matching the success path's content or None), so both observers omit empty content identically rather than one rendering "" and the other dropping it on a truthiness gate. The OpenAI wire can't currently produce empty content on the structured path (an empty assistant message with no tool calls fails earlier as provider_invalid_response), so this is a defensive builder projection, verified by a builder-direct test.
  • Test-coverage: the Langfuse conformance harness's _assert_observation never checked statusMessage — so 123's category assertion (and 130/137/138's) was a silent no-op. Added the assertion.
  • Refreshed a stale _typed_event_metadata docstring, dropped a docstring spec ref, and completed the CHANGELOG response_id/response_model listing.

Full suite green (1716 passed), pyright clean.

PR C of proposal 0082, completing the 3-PR split with the Langfuse
failed-Generation rendering. 0082 is now fully implemented.

For a structured_output_invalid failure the bundled Langfuse observer
renders the response-side surface on the ERROR Generation like a
completion: output (payload-gated) + usage on the Generation, and
finish_reason / response_id / response_model in metadata (the
completion-only isinstance guard widened to include the category),
alongside the existing level=ERROR + statusMessage=category. Every
other failure category is unchanged. Fixture 123 is driven in the
dedicated Langfuse harness (response_schema threaded + expected_error
handled). conformance.toml marks 0082 implemented.

Also folds in the whole-proposal adversarial review over all three PRs:

- Cross-observer consistency: the failure event builders project empty
  output_content to None (matching the success path's content-or-None),
  so both observers omit empty content identically. The OpenAI wire
  cannot currently produce empty content on the structured path, so this
  is a defensive builder projection with a builder-direct test.
- The Langfuse conformance harness now asserts observation statusMessage
  (previously a silent no-op, so 123's category assertion did not run;
  also affected fixtures 130/137/138).
- Refreshed a stale _typed_event_metadata docstring, dropped a docstring
  spec ref, and completed the CHANGELOG response id/model listing.
Copilot AI review requested due to automatic review settings July 23, 2026 18:40

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Completes proposal 0082’s observability work by rendering structured_output_invalid response-surface details on Langfuse ERROR Generations (mirroring completion rendering and OTel parity), and updates conformance + release notes to mark 0082 fully implemented.

Changes:

  • Render payload-gated output plus usage on Langfuse failed Generations for structured_output_invalid, and emit response-side metadata (finish_reason, response_id, response_model).
  • Extend Langfuse conformance harness to drive fixture 123 via response_schema and assert statusMessage; add focused unit tests for rendered vs redacted output.
  • Ensure empty structured-failure content is projected to None in OpenAI event builders for cross-observer parity; mark 0082 implemented in conformance.toml and update CHANGELOG.md.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/unit/test_observability_langfuse.py Adds unit tests covering Langfuse failed-Generation rendering (payload on/off).
tests/unit/test_llm_provider.py Pins builder behavior: empty structured-failure content projects to None.
tests/conformance/test_observability.py Keeps case 123 out of the generic observability harness with updated rationale.
tests/conformance/test_observability_langfuse.py Drives Langfuse fixture 123 via structured path; strengthens observation assertions (incl. statusMessage).
src/openarmature/observability/langfuse/observer.py Implements Langfuse ERROR Generation rendering for 0082 response-surface on structured_output_invalid.
src/openarmature/llm/providers/openai.py Projects empty raw_content to None in failed + retry-attempt typed events.
conformance.toml Marks proposal 0082 as implemented and updates the status note.
CHANGELOG.md Updates 0.17.0 entry to include Langfuse rendering details for 0082.

Comment thread tests/unit/test_observability_langfuse.py
Comment thread tests/conformance/test_observability_langfuse.py
Comment thread src/openarmature/observability/langfuse/observer.py Outdated
Address CoPilot review threads on PR #232 (0082 Langfuse
failed-Generation rendering):

- Assert metadata.response_id on the failed-Generation unit test.
  The event set it but only response_model was pinned, so a
  regression dropping response_id would have passed.
- Assert raised_from against the raised NodeException in the linear
  conformance path. Fixture 123 declares it but nothing checked it.
  Category is not asserted on the exception (its category is always
  node_exception); it rides on the Generation statusMessage.
- Restructure renders_response_side to an explicit if/else so the
  failure branch is obvious. No behavior change.
Copilot AI review requested due to automatic review settings July 23, 2026 19:06

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

@chris-colinsky
chris-colinsky merged commit f752b54 into main Jul 23, 2026
7 checks passed
@chris-colinsky
chris-colinsky deleted the feature/0082-langfuse-failed-generation branch July 23, 2026 19:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants